package com.common.app.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import com.common.app.R
import com.common.base.utils.ViewUtils.dp2px

/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：13/6/2025
 *
 * 描述：
 * 分段进度条
 * 特点：
 * 1. 进度条分为多段，每段颜色可配置
 * 2. 段间有间距，间距可配置
 * 3. 进度条左右两端为圆角
 * 4. 带有跟随进度移动的mark图标
 * 5. mark图标在段间空白处会自动跳跃
 * 6. 支持自定义每段占总长度的比例
 *
 * 修订历史：
 *
 */
class SegmentProgressBar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    // 画笔
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

    // 进度条矩形区域
    private val rectF = RectF()

    // 路径（用于绘制特殊形状）
    private val path = Path()

    // 进度条高度
    private var progressHeight = dp2px(10f)

    // 进度条圆角半径
    private var cornerRadius = dp2px(5f)

    // 段间距
    private var segmentGap = dp2px(5f)

    // Mark图标底部边距
    private var segmentMarkBotMargin = dp2px(2f)

    // 段数量
    private var segmentCount = 4

    // 当前进度值
    private var progress = 0

    // 最大进度值
    private var maxProgress = 100

    // 兼容旧版本的单个Mark图标
    private var markDrawable: Drawable? = null

    // Mark图标数组
    private var markDrawables: Array<Drawable?> = arrayOfNulls(0)

    // Mark图标大小
    private var markSize = dp2px(20f)

    // 段颜色数组
    private var segmentColors = intArrayOf(
        Color.parseColor("#FF4A4A"),
        Color.parseColor("#FFCA43"),
        Color.parseColor("#63A56A"),
        Color.parseColor("#3977FE")
    )

    // 未完成段颜色透明度
    private var unreachedAlpha = 77 // 30% 透明度

    // 段比例数组，每个元素表示该段占总长度的比例（0.0-1.0），所有元素之和应为1.0
    private var segmentRatios: FloatArray = FloatArray(0)

    init {
        // 获取自定义属性
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.SegmentProgressBar)
        progressHeight = typedArray.getDimension(R.styleable.SegmentProgressBar_segmentProgressHeight, progressHeight)
        cornerRadius = typedArray.getDimension(R.styleable.SegmentProgressBar_segmentCornerRadius, cornerRadius)
        segmentGap = typedArray.getDimension(R.styleable.SegmentProgressBar_segmentGap, segmentGap)
        segmentMarkBotMargin = typedArray.getDimension(R.styleable.SegmentProgressBar_segmentMarkBotMargin, segmentMarkBotMargin)
        segmentCount = typedArray.getInt(R.styleable.SegmentProgressBar_segmentCount, segmentCount)
        progress = typedArray.getInt(R.styleable.SegmentProgressBar_segmentProgress, progress)
        maxProgress = typedArray.getInt(R.styleable.SegmentProgressBar_segmentMaxProgress, maxProgress)
        markDrawable = typedArray.getDrawable(R.styleable.SegmentProgressBar_segmentMarkIcon)
        markSize = typedArray.getDimension(R.styleable.SegmentProgressBar_segmentMarkSize, markSize)
        unreachedAlpha = typedArray.getInt(R.styleable.SegmentProgressBar_segmentUnreachedAlpha, unreachedAlpha)

        // 获取段颜色数组
        val colorsResId = typedArray.getResourceId(R.styleable.SegmentProgressBar_segmentColors, 0)
        if (colorsResId != 0) {
            val colors = resources.getIntArray(colorsResId)
            if (colors.isNotEmpty()) {
                segmentColors = colors
            }
        }

        // 获取Mark图标数组
        val markIconsResId = typedArray.getResourceId(R.styleable.SegmentProgressBar_segmentMarkIcons, 0)
        if (markIconsResId != 0) {
            try {
                // 尝试获取drawable数组
                val typedArray = resources.obtainTypedArray(markIconsResId)
                markDrawables = Array(typedArray.length()) { i ->
                    typedArray.getDrawable(i)
                }
                typedArray.recycle()
            } catch (e: Exception) {
                // 如果获取失败，使用单个图标
                markDrawables = arrayOfNulls(0)
            }
        }

        typedArray.recycle()

        // 初始化段比例数组为平均分配
        initDefaultSegmentRatios()

        // 确保段颜色数组长度与段数量一致
        if (segmentColors.size != segmentCount) {
            val newColors = IntArray(segmentCount)
            for (i in 0 until segmentCount) {
                newColors[i] = if (i < segmentColors.size) segmentColors[i] else segmentColors[i % segmentColors.size]
            }
            segmentColors = newColors
        }

        // 确保Mark图标数组长度与段数量一致
        if (markDrawables.isEmpty() && markDrawable != null) {
            // 如果没有设置图标数组但设置了单个图标，则用单个图标填充数组
            markDrawables = Array(segmentCount) { markDrawable }
        } else if (markDrawables.size != segmentCount) {
            val newDrawables = arrayOfNulls<Drawable>(segmentCount)
            for (i in 0 until segmentCount) {
                newDrawables[i] = if (i < markDrawables.size && markDrawables[i] != null) {
                    markDrawables[i]
                } else if (markDrawables.isNotEmpty()) {
                    markDrawables[i % markDrawables.size]
                } else {
                    markDrawable
                }
            }
            markDrawables = newDrawables
        }
    }

    /**
     * 初始化默认段比例（平均分配）
     */
    private fun initDefaultSegmentRatios() {
        segmentRatios = FloatArray(segmentCount) { 1.0f / segmentCount }
    }

    /**
     * 计算每段的实际宽度
     */
    private fun calculateSegmentWidths(availableWidth: Float): FloatArray {
        val totalGapWidth = segmentGap * (segmentCount - 1)
        val progressWidth = availableWidth - totalGapWidth

        return FloatArray(segmentCount) { i ->
            progressWidth * segmentRatios[i]
        }
    }

    /**
     * 计算段的起始位置
     */
    private fun calculateSegmentPositions(segmentWidths: FloatArray, startX: Float): FloatArray {
        val positions = FloatArray(segmentCount)
        var currentX = startX

        for (i in 0 until segmentCount) {
            positions[i] = currentX
            currentX += segmentWidths[i] + segmentGap
        }

        return positions
    }

    /**
     * 计算当前进度对应的段和段内进度比例
     */
    private fun calculateCurrentSegmentProgress(): Pair<Int, Float> {
        val progressRatio = progress.toFloat() / maxProgress
        var accumulatedRatio = 0f

        for (i in 0 until segmentCount) {
            val segmentEndRatio = accumulatedRatio + segmentRatios[i]
            if (progressRatio <= segmentEndRatio) {
                val segmentProgressRatio = if (segmentRatios[i] > 0) {
                    (progressRatio - accumulatedRatio) / segmentRatios[i]
                } else {
                    0f
                }
                return Pair(i, segmentProgressRatio.coerceIn(0f, 1f))
            }
            accumulatedRatio = segmentEndRatio
        }

        return Pair(segmentCount - 1, 1f)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val height: Int

        // 计算View高度，需要考虑进度条高度和Mark图标高度
        val minHeight = progressHeight.toInt() + paddingTop + paddingBottom
        val markHeight = if (markDrawables.isNotEmpty() || markDrawable != null) markSize.toInt() + dp2px(5f).toInt() else 0
        height = when (heightMode) {
            MeasureSpec.EXACTLY -> MeasureSpec.getSize(heightMeasureSpec)
            else -> minHeight + markHeight
        }

        setMeasuredDimension(width, height)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val width = width - paddingLeft - paddingRight
        val height = height - paddingTop - paddingBottom

        // 计算进度条的垂直位置
        val progressY = if (markDrawables.isNotEmpty() || markDrawable != null) {
            paddingTop + markSize + segmentMarkBotMargin//mark图标底部和进度条顶部的间距
        } else {
            paddingTop + (height - progressHeight) / 2
        }

        // 绘制背景进度条（未完成部分）
        drawBackground(canvas, width, progressY)

//        // 绘制已完成的进度段
//        drawSegments(canvas, width, progressY)

        // 绘制Mark图标
        drawMark(canvas, width, progressY)
    }

    /**
     * 绘制背景进度条
     */
    private fun drawBackground(canvas: Canvas, width: Int, progressY: Float) {
        val availableWidth = width - markSize
        val segmentWidths = calculateSegmentWidths(availableWidth)
        val segmentPositions = calculateSegmentPositions(segmentWidths, paddingLeft + markSize / 2)

        // 绘制每一段背景
        for (i in 0 until segmentCount) {
            // 使用对应段的颜色，但设置透明度
            val color = segmentColors[i]
            val alpha = Color.alpha(color) * unreachedAlpha / 255
            val r = Color.red(color)
            val g = Color.green(color)
            val b = Color.blue(color)
            paint.color = Color.argb(alpha, r, g, b)

            val left = segmentPositions[i]
            val right = left + segmentWidths[i]

            rectF.left = left
            rectF.top = progressY
            rectF.right = right
            rectF.bottom = progressY + progressHeight

            // 只有第一段的左边和最后一段的右边需要圆角
            if (i == 0) {
                // 第一段，左边圆角
                path.reset()
                path.addRoundRect(rectF, floatArrayOf(
                    cornerRadius, cornerRadius, // 左上角
                    0f, 0f, // 右上角
                    0f, 0f, // 右下角
                    cornerRadius, cornerRadius  // 左下角
                ), Path.Direction.CW)
                canvas.drawPath(path, paint)
            } else if (i == segmentCount - 1) {
                // 最后一段，右边圆角
                path.reset()
                path.addRoundRect(rectF, floatArrayOf(
                    0f, 0f, // 左上角
                    cornerRadius, cornerRadius, // 右上角
                    cornerRadius, cornerRadius, // 右下角
                    0f, 0f  // 左下角
                ), Path.Direction.CW)
                canvas.drawPath(path, paint)
            } else {
                // 中间段，无圆角
                canvas.drawRect(rectF, paint)
            }
        }
    }

    /**
     * 绘制已完成的进度段
     */
    private fun drawSegments(canvas: Canvas, width: Int, progressY: Float) {
        val availableWidth = width - markSize
        val segmentWidths = calculateSegmentWidths(availableWidth)
        val segmentPositions = calculateSegmentPositions(segmentWidths, paddingLeft + markSize / 2)

        // 计算当前进度对应的段和段内进度
        val (currentSegment, segmentProgress) = calculateCurrentSegmentProgress()

        // 绘制已完成的整段
        for (i in 0 until currentSegment) {
            drawSegmentWithRatio(canvas, i, segmentWidths[i], segmentPositions[i], progressY, 1.0f)
        }

        // 绘制当前进行中的段
        if (currentSegment < segmentCount) {
            val segmentProgressRatio = segmentProgress
            drawSegmentWithRatio(canvas, currentSegment, segmentWidths[currentSegment], segmentPositions[currentSegment], progressY, segmentProgressRatio)
        }
    }

    /**
     * 绘制单个进度段（支持自定义宽度）
     */
    private fun drawSegmentWithRatio(canvas: Canvas, segmentIndex: Int, segmentWidth: Float, segmentLeft: Float, progressY: Float, progressRatio: Float) {
        // 使用对应段的颜色，不透明
        paint.color = segmentColors[segmentIndex]

        val left = segmentLeft
        val right = left + segmentWidth * progressRatio

        // 确保第一段在进度很小时也能显示圆角
        if (segmentIndex == 0 && progressRatio > 0 && progressRatio < 0.1f) {
            val minWidth = cornerRadius * 2
            rectF.left = left
            rectF.top = progressY
            rectF.right = left + minWidth.coerceAtMost(segmentWidth * progressRatio)
            rectF.bottom = progressY + progressHeight

            path.reset()
            path.addRoundRect(rectF, floatArrayOf(
                cornerRadius, cornerRadius, // 左上角
                0f, 0f, // 右上角
                0f, 0f, // 右下角
                cornerRadius, cornerRadius  // 左下角
            ), Path.Direction.CW)
            canvas.drawPath(path, paint)
        } else {
            rectF.left = left
            rectF.top = progressY
            rectF.right = right
            rectF.bottom = progressY + progressHeight

            // 处理圆角
            if (segmentIndex == 0) {
                // 第一段，左边需要圆角
                path.reset()
                path.addRoundRect(rectF, floatArrayOf(
                    cornerRadius, cornerRadius, // 左上角
                    0f, 0f, // 右上角
                    0f, 0f, // 右下角
                    cornerRadius, cornerRadius  // 左下角
                ), Path.Direction.CW)
                canvas.drawPath(path, paint)
            } else if (segmentIndex == segmentCount - 1) {
                // 最后一段，右边需要圆角
                path.reset()
                path.addRoundRect(rectF, floatArrayOf(
                    0f, 0f, // 左上角
                    cornerRadius, cornerRadius, // 右上角
                    cornerRadius, cornerRadius, // 右下角
                    0f, 0f  // 左下角
                ), Path.Direction.CW)
                canvas.drawPath(path, paint)
            } else {
                // 中间段，无圆角
                canvas.drawRect(rectF, paint)
            }
        }
    }

    /**
     * 绘制Mark图标
     */
    private fun drawMark(canvas: Canvas, width: Int, progressY: Float) {
        // 当进度为0时，不绘制mark图标
        if (progress == 0 || (markDrawables.isEmpty() && markDrawable == null)) return

        val availableWidth = width - markSize
        val segmentWidths = calculateSegmentWidths(availableWidth)
        val segmentPositions = calculateSegmentPositions(segmentWidths, paddingLeft + markSize / 2)

        // 计算当前进度对应的段和段内进度
        val (currentSegment, segmentProgressRatio) = calculateCurrentSegmentProgress()

        // 计算Mark的X坐标
        val markX = if (progress >= maxProgress) {
            // 进度达到最大值，Mark位于最右侧
            paddingLeft + width - markSize / 2
        } else {
            // 正常情况下，Mark跟随进度移动
            val segmentLeft = segmentPositions[currentSegment]
            segmentLeft + segmentWidths[currentSegment] * segmentProgressRatio
        }

        // 设置Mark图标的位置
        val markLeft = markX - markSize / 2
        val markTop = paddingTop.toFloat()
        val markRight = markLeft + markSize
        val markBottom = markTop + markSize

        // 获取当前段对应的图标
        val currentDrawable = if (currentSegment < markDrawables.size && markDrawables[currentSegment] != null) {
            markDrawables[currentSegment]
        } else if (markDrawables.isNotEmpty()) {
            markDrawables[currentSegment % markDrawables.size]
        } else {
            markDrawable
        }

        currentDrawable?.setBounds(markLeft.toInt(), markTop.toInt(), markRight.toInt(), markBottom.toInt())
        currentDrawable?.draw(canvas)
    }

    /**
     * 设置进度值
     */
    fun setProgress(progress: Int) {
        this.progress = progress.coerceIn(0, maxProgress)
        invalidate()
    }

    /**
     * 设置最大进度值
     */
    fun setMaxProgress(maxProgress: Int) {
        this.maxProgress = maxProgress
        this.progress = progress.coerceIn(0, maxProgress)
        invalidate()
    }

    /**
     * 设置段数量
     */
    fun setSegmentCount(count: Int) {
        this.segmentCount = count

        // 重新初始化段比例数组
        initDefaultSegmentRatios()

        // 更新段颜色数组
        val newColors = IntArray(segmentCount)
        for (i in 0 until segmentCount) {
            newColors[i] = if (i < segmentColors.size) segmentColors[i] else segmentColors[i % segmentColors.size]
        }
        segmentColors = newColors

        // 更新Mark图标数组
        val newDrawables = arrayOfNulls<Drawable>(segmentCount)
        for (i in 0 until segmentCount) {
            newDrawables[i] = if (i < markDrawables.size && markDrawables[i] != null) {
                markDrawables[i]
            } else if (markDrawables.isNotEmpty()) {
                markDrawables[i % markDrawables.size]
            } else {
                markDrawable
            }
        }
        markDrawables = newDrawables

        invalidate()
    }

    /**
     * 设置段颜色数组
     */
    fun setSegmentColors(colors: IntArray) {
        if (colors.isEmpty()) return

        // 确保段颜色数组长度与段数量一致
        val newColors = IntArray(segmentCount)
        for (i in 0 until segmentCount) {
            newColors[i] = if (i < colors.size) colors[i] else colors[i % colors.size]
        }
        segmentColors = newColors
        invalidate()
    }

    /**
     * 设置段间距
     */
    fun setSegmentGap(gap: Float) {
        this.segmentGap = dp2px(gap)
        invalidate()
    }

    /**
     * 设置Mark图标
     */
    fun setMarkDrawable(drawable: Drawable?) {
        this.markDrawable = drawable
        // 更新Mark图标数组
        markDrawables = Array(segmentCount) { drawable }
        requestLayout()
        invalidate()
    }

    /**
     * 设置Mark图标数组
     */
    fun setMarkDrawables(drawables: Array<Drawable?>) {
        if (drawables.isEmpty()) return

        // 确保Mark图标数组长度与段数量一致
        val newDrawables = arrayOfNulls<Drawable>(segmentCount)
        for (i in 0 until segmentCount) {
            newDrawables[i] = if (i < drawables.size && drawables[i] != null) {
                drawables[i]
            } else if (drawables.isNotEmpty()) {
                drawables[i % drawables.size]
            } else {
                markDrawable
            }
        }
        markDrawables = newDrawables
        requestLayout()
        invalidate()
    }

    /**
     * 设置未完成段的透明度
     */
    fun setUnreachedAlpha(alpha: Int) {
        this.unreachedAlpha = alpha.coerceIn(0, 255)
        invalidate()
    }

    /**
     * 设置段比例数组
     * @param ratios 每段占总长度的比例数组，所有元素之和应为1.0
     */
    fun setSegmentRatios(ratios: FloatArray) {
        if (ratios.isEmpty() || ratios.size != segmentCount) {
            throw IllegalArgumentException("段比例数组长度必须与段数量一致")
        }

        val sum = ratios.sum()
        if (sum <= 0) {
            throw IllegalArgumentException("段比例数组元素之和必须大于0")
        }

        // 归一化比例数组，确保总和为1.0
        segmentRatios = FloatArray(ratios.size) { i -> ratios[i] / sum }
        invalidate()
    }

    /**
     * 获取当前段比例数组
     */
    fun getSegmentRatios(): FloatArray {
        return segmentRatios.copyOf()
    }

    /**
     * 设置指定段的比例
     * @param segmentIndex 段索引
     * @param ratio 该段的比例
     */
    fun setSegmentRatio(segmentIndex: Int, ratio: Float) {
        if (segmentIndex < 0 || segmentIndex >= segmentCount) {
            throw IndexOutOfBoundsException("段索引超出范围")
        }

        if (ratio <= 0) {
            throw IllegalArgumentException("段比例必须大于0")
        }

        segmentRatios[segmentIndex] = ratio

        // 归一化所有比例
        val sum = segmentRatios.sum()
        for (i in segmentRatios.indices) {
            segmentRatios[i] = segmentRatios[i] / sum
        }

        invalidate()
    }
}